#set( $symbol_pound = '#' )
#set( $symbol_dollar = '$' )
#set( $symbol_escape = '\' )
package ${package}.config.feign;

import feign.Client;
import feign.Logger;
import feign.Request;
import feign.Response;
import feign.Retryer;
import feign.Util;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;

import java.io.IOException;

import static feign.Util.decodeOrDefault;

@Configuration
@EnableFeignClients(basePackages = {"${package}"})
@Slf4j
@ConditionalOnProperty(prefix = "spring.cloud.openfeign", name = "enabled", havingValue = "true")
@Order(1)
public class FeignConfig {

    @Bean
    public Client feignClient(LoadBalancerClient loadBalancerClient, LoadBalancerClientFactory loadBalancerClientFactory) {
        // 创建 OkHttpClient 实例
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .connectTimeout(5, java.util.concurrent.TimeUnit.SECONDS) // 连接超时
                .readTimeout(5, java.util.concurrent.TimeUnit.SECONDS)    // 读取超时
                .writeTimeout(5, java.util.concurrent.TimeUnit.SECONDS)   // 写入超时
                .build();
        feign.okhttp.OkHttpClient client = new feign.okhttp.OkHttpClient(okHttpClient);
        // 返回 Feign 的 OkHttp 客户端
        return  new FeignBlockingLoadBalancerClient(client, loadBalancerClient, loadBalancerClientFactory);
    }
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }

    @Bean
    Retryer feignRetryer() {
        return Retryer.NEVER_RETRY;
    }

    @Bean
    @ConditionalOnMissingBean(Logger.class)
    Logger feignLogger(){
        return new Logger(){

            @Override
            protected void log(String configKey, String format, Object... args) {
                // logger.info("------  {}" ,configKey);
            }
            @Override
            protected Response logAndRebufferResponse(String configKey, Level logLevel, Response response,
                                                      long elapsedTime) throws IOException {
                String reason = response.reason() != null ?  response.reason() : "null";
                int status = response.status();
                String uuid = null;
                String url = null;
                if(response.request() != null) {
                    url = response.request().url();
                }
                if (response.body() != null && !(status == 204 || status == 205)) {
                    byte[] bodyData = Util.toByteArray(response.body().asInputStream());
                    log.info("Receive feign response: feign_uuid: "+ uuid + ", cost: "+ + elapsedTime + "ms, reason: " +  reason +", body: " + decodeOrDefault(bodyData, Util.UTF_8, "Binary data"));
                    return response.toBuilder().body(bodyData).build();
                } else{
                    log.info("Receive feign response: feign_uuid: "+ uuid + ", cost: "+ + elapsedTime + "ms, reason: " +  reason );
                }
                return response;
            }
            @Override
            protected void logRequest(String configKey, Level logLevel, Request request) {
                String uuid = null;
                String url = request.url();
                String bodyText = null;
                if (request.body() != null) {
                    bodyText = request.charset() != null ? new String(request.body(), request.charset()) : null;
                }
                log.info("Send feign request: feign_uuid: " + uuid + ", url: " + url + ", body: " +bodyText);
                super.logRequest(configKey, logLevel, request);
            }
        };
    }
}
